package com.kfyang.manualgear.daoplugin.linemarker;

import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo;
import com.intellij.codeInsight.daemon.RelatedItemLineMarkerProvider;
import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import com.kfyang.manualgear.daoplugin.NavigationIcon;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.yaml.psi.YAMLDocument;
import org.jetbrains.yaml.psi.YAMLKeyValue;
import org.jetbrains.yaml.psi.YAMLMapping;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;

public class YamlToDaoLineMarkerProvider extends RelatedItemLineMarkerProvider {

    @Override
    protected void collectNavigationMarkers(@NotNull PsiElement element, @NotNull Collection<? super RelatedItemLineMarkerInfo<?>> result) {
        if (element instanceof YAMLKeyValue namespacePair && namespacePair.getKeyText().equals("namespace")
                && namespacePair.getParent() instanceof YAMLMapping yamlMapping && yamlMapping.getParent() instanceof YAMLDocument) {
            Project project = element.getProject();
            PsiClass psiClass = JavaPsiFacade.getInstance(project).findClass(namespacePair.getValueText(), GlobalSearchScope.allScope(project));
            if (psiClass == null) {
                return;
            }
            NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(NavigationIcon.NAV_ICON)
                .setAlignment(GutterIconRenderer.Alignment.CENTER)
                .setTarget(psiClass)
                .setTooltipTitle("Navigation to Target Interface");

            result.add(builder.createLineMarkerInfo(namespacePair.getKey()));
            return;
        }

        if (!(element instanceof YAMLKeyValue keyValue) || !keyValue.getKey().getText().equals("methodName") ||
            !(keyValue.getParent() instanceof YAMLMapping yamlMapping) ||
            !(yamlMapping.getParent() instanceof YAMLDocument)
        ) {
            return;
        }

        PsiFile topLevelFile = InjectedLanguageManager.getInstance(element.getProject()).getTopLevelFile(element);
        String yamlFileName = topLevelFile.getName();
        String className = yamlFileName.substring(0, yamlFileName.lastIndexOf('.'));

        PsiFile[] classFiles = PsiShortNamesCache.getInstance(element.getProject())
            .getFilesByName(className + ".java");
        if (classFiles.length != 1) {
            return;
        }
        PsiJavaFile psiJavaFile = (PsiJavaFile) classFiles[0];

        List<PsiClass> psiClasses = Arrays.stream(psiJavaFile.getClasses())
            .filter(psiClass -> psiClass.getName().equals(className))
            .toList();
        if (psiClasses.size() != 1) {
            return;
        }
        PsiClass psiClass = psiClasses.get(0);
        if (!psiClass.isInterface()) {
            return;
        }
        PsiMethod[] methods = psiClass.findMethodsByName(keyValue.getValueText(), false);
        if (methods.length != 1) {
            return;
        }
        PsiMethod method = methods[0];
        NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(NavigationIcon.NAV_ICON)
            .setAlignment(GutterIconRenderer.Alignment.CENTER)
            .setTarget(method)
            .setTooltipTitle("Navigation to Target Method In Interface");

        result.add(builder.createLineMarkerInfo(keyValue.getKey()));
    }
}
